package com.cyx.friend.service.exam.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.cyx.common.core.constants.Constants;
import com.cyx.common.core.domain.TableDataInfo;
import com.cyx.common.core.utils.ThreadLocalUtil;
import com.cyx.friend.domain.exam.dto.ExamQueryDTO;
import com.cyx.friend.domain.exam.vo.ExamVO;
import com.cyx.friend.manager.ExamCacheManager;
import com.cyx.friend.mapper.exam.ExamMapper;
import com.cyx.friend.service.exam.IExamService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ExamServiceImpl implements IExamService {

    @Autowired
    private ExamMapper examMapper;

    @Autowired
    private ExamCacheManager examCacheManager;

    @Override
    public List<ExamVO> list(ExamQueryDTO examQueryDTO) {
        PageHelper.startPage(examQueryDTO.getPageNum(), examQueryDTO.getPageSize());
        return examMapper.selectExamList(examQueryDTO);
    }

    @Override
    public TableDataInfo redisList(ExamQueryDTO examQueryDTO) {
        //TODO AOP 参数校验

        // 从redis中获取数据并返回
        // 先获取redis中数据的总数
        Long total = examCacheManager.getListSize(examQueryDTO.getType(), null);
        List<ExamVO> examVOList;
        // 判断redis中是否有数据
        if(total == null || total <= 0) {
            // 如果redis中没有数据，从数据库中查询数据
            examVOList = list(examQueryDTO);
            // 刷新缓存，将数据库数据同步到redis 中
            examCacheManager.refreshCache(examQueryDTO, null);
            total = new PageInfo<>(examVOList).getTotal();
        } else {
            // 从redis中获取所有的竞赛列表
            examVOList = examCacheManager.getExamVOList(examQueryDTO, null);
            // 根据传入参数过滤
            if(examQueryDTO.getType() == 0) examVOList = examVOList.stream().filter(examVO -> examVO.getEndTime().isAfter(LocalDateTime.now())).collect(Collectors.toList());
            else examVOList = examVOList.stream().filter(examVO -> examVO.getEndTime().isBefore(LocalDateTime.now())).collect(Collectors.toList());
            // 定义时间格式转换对象
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime startTime;
            LocalDateTime endTime;
            // 当参数中的时间不为空时，开始过滤
            if(StringUtils.isNotBlank(examQueryDTO.getStartTime()) && StringUtils.isNotBlank(examQueryDTO.getEndTime())) {
                // 格式转换 String -> LocalDateTime
                startTime = LocalDateTime.parse(examQueryDTO.getStartTime(), df);
                endTime = LocalDateTime.parse(examQueryDTO.getEndTime(), df);
                // redis中有数据，直接从redis中获取数据
                examVOList = examVOList.stream()
                        .filter(examVO -> examVO.getStartTime().isAfter(startTime) && examVO.getEndTime().isBefore(endTime))
                        .collect(Collectors.toList());
            }
            // 如果是正常情况，redis中的数据和数据库中一致，不需要操作
            // 但是，如果在获取数据时，发现数据异常，那么就需要重新刷新缓存，刷新缓存之后，total可能会变，所有要重新获取一下
//            total = examCacheManager.getListSize(examQueryDTO.getType());
            total = (long) examVOList.size();
        }
        if(CollectionUtil.isEmpty(examVOList)){
            return TableDataInfo.empty();
        }
        assembleExamVOList(examVOList);
        // 获取符合查询条件的总记录数
        return TableDataInfo.success(examVOList, total);
    }

    @Override
    public String getFirstQuestion(Long examId) {
        checkAndRefresh(examId);
        return examCacheManager.getFirstQuestion(examId).toString();
    }

    @Override
    public String preQuestion(Long examId, Long questionId) {
        checkAndRefresh(examId);
        return examCacheManager.preQuestion(examId, questionId).toString();
    }

    @Override
    public String nextQuestion(Long examId, Long questionId) {
        checkAndRefresh(examId);
        return examCacheManager.nextQuestion(examId, questionId).toString();
    }

    private void checkAndRefresh(Long examId) {
        Long listSize = examCacheManager.getExamQuestionListSize(examId);
        if(listSize == null || listSize <= 0) {
            examCacheManager.refreshExamQuestionCache(examId);
        }
    }

    private void assembleExamVOList(List<ExamVO> examVOList) {
        // 先从ThreadLocal中获取当前用户id
        Long id = ThreadLocalUtil.get(Constants.USER_ID, Long.class);
        // 再通过id获取该用户所有的竞赛列表
        List<Long> userExamIdList = examCacheManager.getAllUserExamList(id);
        // 如果userExamIdList为空，直接结束
        if(CollectionUtil.isEmpty(userExamIdList)) return;
        // 遍历examVOList，如果里面的元素在userExamList中存在，就把对应的enter设为true
        for(ExamVO examVO : examVOList) {
            if(userExamIdList.contains(examVO.getExamId())) {
                examVO.setEnter(true);
            }
        }
    }
}
